home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / sh.set.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-01  |  19.9 KB  |  944 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.set.c,v 3.2 1991/07/17 21:52:22 christos Exp $ */
  2. /*
  3.  * sh.set.c: Setting and Clearing of variables
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "config.h"
  38. RCSID("$Id: sh.set.c,v 3.2 1991/07/17 21:52:22 christos Exp $")
  39.  
  40. #include "sh.h"
  41. #include "ed.h"
  42. #include "tw.h"
  43.  
  44. extern Char HistLit;
  45. extern bool GotTermCaps;
  46.  
  47. static    Char        *getinx        __P((Char *, int *));
  48. static    void         asx        __P((Char *, int, Char *));
  49. static    struct varent     *getvx        __P((Char *, int));
  50. static    Char        *xset        __P((Char *, Char ***));
  51. static    Char        *operate    __P((int, Char *, Char *));
  52. static    void          putn1        __P((int));
  53. static    struct varent    *madrof        __P((Char *, struct varent *));
  54. static    void         unsetv1    __P((struct varent *));
  55. static    void         exportpath    __P((Char **));
  56. #ifdef __MINT__
  57. static    void         exportsuffixes __P((Char **));
  58. #endif
  59. static    void         balance    __P((struct varent *, int, int));
  60.  
  61. /*
  62.  * C Shell
  63.  */
  64.  
  65. /*ARGSUSED*/
  66. void
  67. doset(v, c)
  68.     register Char **v;
  69.     struct command *c;
  70. {
  71.     register Char *p;
  72.     Char   *vp, op;
  73.     Char  **vecp;
  74.     bool    hadsub;
  75.     int     subscr;
  76.  
  77.     v++;
  78.     p = *v++;
  79.     if (p == 0) {
  80.     prvars();
  81.     return;
  82.     }
  83.     do {
  84.     hadsub = 0;
  85.     vp = p;
  86.     if (letter(*p))
  87.         for (; alnum(*p); p++)
  88.         continue;
  89.     if (vp == p || !letter(*vp))
  90.         stderror(ERR_NAME | ERR_VARBEGIN);
  91.     if ((p - vp) > MAXVARLEN) {
  92.         stderror(ERR_NAME | ERR_VARTOOLONG);
  93.         return;
  94.     }
  95.     if (*p == '[') {
  96.         hadsub++;
  97.         p = getinx(p, &subscr);
  98.     }
  99.     if (op = *p) {
  100.         *p++ = 0;
  101.         if (*p == 0 && *v && **v == '(')
  102.         p = *v++;
  103.     }
  104.     else if (*v && eq(*v, STRequal)) {
  105.         op = '=', v++;
  106.         if (*v)
  107.         p = *v++;
  108.     }
  109.     if (op && op != '=')
  110.         stderror(ERR_NAME | ERR_SYNTAX);
  111.     if (eq(p, STRLparen)) {
  112.         register Char **e = v;
  113.  
  114.         if (hadsub)
  115.         stderror(ERR_NAME | ERR_SYNTAX);
  116.         for (;;) {
  117.         if (!*e)
  118.             stderror(ERR_NAME | ERR_MISSING, ')');
  119.         if (**e == ')')
  120.             break;
  121.         e++;
  122.         }
  123.         p = *e;
  124.         *e = 0;
  125.         vecp = saveblk(v);
  126.         set1(vp, vecp, &shvhed);
  127.         *e = p;
  128.         v = e + 1;
  129.     }
  130.     else if (hadsub)
  131.         asx(vp, subscr, Strsave(p));
  132.     else
  133.         set(vp, Strsave(p));
  134.     if (eq(vp, STRpath)) {
  135.         exportpath(adrof(STRpath)->vec);
  136.         dohash(NULL, NULL);
  137.     }
  138. #ifdef __MINT__
  139.     else if (eq(vp, STRsuffixes)) {
  140.         exportsuffixes(adrof(STRsuffixes)->vec);
  141.         dohash(NULL, NULL);
  142.     }
  143. #endif
  144.     else if (eq(vp, STRhistchars)) {
  145.         register Char *pn = value(STRhistchars);
  146.  
  147.         HIST = *pn++;
  148.         HISTSUB = *pn;
  149.     }
  150.     else if (eq(vp, STRhistlit)) {
  151.         HistLit = 1;
  152.     }
  153.     else if (eq(vp, STRuser)) {
  154.         Setenv(STRUSER, value(vp));
  155.         Setenv(STRLOGNAME, value(vp));
  156.     }
  157.     else if (eq(vp, STRwordchars)) {
  158.         word_chars = value(vp);
  159.     }
  160.     else if (eq(vp, STRterm)) {
  161. #ifdef DOESNT_WORK_RIGHT
  162.         register Char *cp;
  163.  
  164. #endif
  165.         Setenv(STRTERM, value(vp));
  166. #ifdef DOESNT_WORK_RIGHT
  167.         cp = getenv("TERMCAP");
  168.         if (cp && (*cp != '/'))    /* if TERMCAP and not a path */
  169.         Unsetenv(STRTERMCAP);
  170. #endif                /* DOESNT_WORK_RIGHT */
  171.         GotTermCaps = 0;
  172.         ed_Init();        /* reset the editor */
  173.     }
  174.     else if (eq(vp, STRhome)) {
  175.         register Char *cp;
  176.  
  177.         cp = Strsave(value(vp));    /* get the old value back */
  178.  
  179.         /*
  180.          * convert to cononical pathname (possibly resolving symlinks)
  181.          */
  182.         cp = dcanon(cp, cp);
  183.  
  184.         set(vp, Strsave(cp));    /* have to save the new val */
  185.  
  186.         /* and now mirror home with HOME */
  187.         Setenv(STRHOME, cp);
  188.         /* fix directory stack for new tilde home */
  189.         dtilde();
  190.         xfree((ptr_t) cp);
  191.     }
  192.     else if (eq(vp, STRedit)) {
  193.         editing = 1;
  194.         /* PWP: add more stuff in here later */
  195.     }
  196.     else if (eq(vp, STRshlvl)) {
  197.         Setenv(STRSHLVL, value(vp));
  198.     }
  199.     else if (eq(vp, STRbackslash_quote)) {
  200.         bslash_quote = 1;
  201.     }
  202.     else if (eq(vp, STRrecognize_only_executables)) {
  203.         tw_clear_comm_list();
  204.     }
  205.     else if (eq(vp, STRwatch)) {
  206.         resetwatch();
  207.     }
  208. #ifdef ALTESC
  209.     else if (eq(vp, STRescchar)) {
  210.         register Char *cp;
  211.  
  212.         cp = value(vp);
  213.         _cmap[escchar] &= ~_ESC;
  214.         escchar = (cp && *cp) ? *cp : '\001';
  215.         _cmap[escchar] |= _ESC;
  216.     }
  217. #endif
  218. #ifdef __MINT__
  219.     else if (eq(vp, STRdosslashes)) {
  220.         STRslash[0] = '\\';
  221.     }
  222. #endif
  223.     } while (p = *v++);
  224. }
  225.  
  226. static Char *
  227. getinx(cp, ip)
  228.     register Char *cp;
  229.     register int *ip;
  230. {
  231.     *ip = 0;
  232.     *cp++ = 0;
  233.     while (*cp && Isdigit(*cp))
  234.     *ip = *ip * 10 + *cp++ - '0';
  235.     if (*cp++ != ']')
  236.     stderror(ERR_NAME | ERR_SUBSCRIPT);
  237.     return (cp);
  238. }
  239.  
  240. static void
  241. asx(vp, subscr, p)
  242.     Char   *vp;
  243.     int     subscr;
  244.     Char   *p;
  245. {
  246.     register struct varent *v = getvx(vp, subscr);
  247.  
  248.     xfree((ptr_t) v->vec[subscr - 1]);
  249.     v->vec[subscr - 1] = globone(p, G_APPEND);
  250. }
  251.  
  252. static struct varent *
  253. getvx(vp, subscr)
  254.     Char   *vp;
  255.     int     subscr;
  256. {
  257.     register struct varent *v = adrof(vp);
  258.  
  259.     if (v == 0)
  260.     udvar(vp);
  261.     if (subscr < 1 || subscr > blklen(v->vec))
  262.     stderror(ERR_NAME | ERR_RANGE);
  263.     return (v);
  264. }
  265.  
  266. /*ARGSUSED*/
  267. void
  268. dolet(v, dummy)
  269.     Char  **v;
  270.     struct command *dummy;
  271. {
  272.     register Char *p;
  273.     Char   *vp, c, op;
  274.     bool    hadsub;
  275.     int     subscr;
  276.  
  277.     v++;
  278.     p = *v++;
  279.     if (p == 0) {
  280.     prvars();
  281.     return;
  282.     }
  283.     do {
  284.     hadsub = 0;
  285.     vp = p;
  286.     if (letter(*p))
  287.         for (; alnum(*p); p++)
  288.         continue;
  289.     if (vp == p || !letter(*vp))
  290.         stderror(ERR_NAME | ERR_VARBEGIN);
  291.     if ((p - vp) > MAXVARLEN)
  292.         stderror(ERR_NAME | ERR_VARTOOLONG);
  293.     if (*p == '[') {
  294.         hadsub++;
  295.         p = getinx(p, &subscr);
  296.     }
  297.     if (*p == 0 && *v)
  298.         p = *v++;
  299.     if (op = *p)
  300.         *p++ = 0;
  301.     else
  302.         stderror(ERR_NAME | ERR_ASSIGN);
  303.  
  304.     /*
  305.      * if there is no expression after the '=' then print a "Syntax Error"
  306.      * message - strike
  307.      */
  308.     if (*p == '\0' && *v == NULL)
  309.         stderror(ERR_NAME | ERR_ASSIGN);
  310.  
  311.     vp = Strsave(vp);
  312.     if (op == '=') {
  313.         c = '=';
  314.         p = xset(p, &v);
  315.     }
  316.     else {
  317.         c = *p++;
  318.         if (any("+-", c)) {
  319.         if (c != op || *p)
  320.             stderror(ERR_NAME | ERR_UNKNOWNOP);
  321.         p = Strsave(STR1);
  322.         }
  323.         else {
  324.         if (any("<>", op)) {
  325.             if (c != op)
  326.             stderror(ERR_NAME | ERR_UNKNOWNOP);
  327.             c = *p++;
  328.             stderror(ERR_NAME | ERR_SYNTAX);
  329.         }
  330.         if (c != '=')
  331.             stderror(ERR_NAME | ERR_UNKNOWNOP);
  332.         p = xset(p, &v);
  333.         }
  334.     }
  335.     if (op == '=')
  336.         if (hadsub)
  337.         asx(vp, subscr, p);
  338.         else
  339.         set(vp, p);
  340.     else if (hadsub) {
  341.         struct varent *gv = getvx(vp, subscr);
  342.  
  343.         asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
  344.     }
  345.     else
  346.         set(vp, operate(op, value(vp), p));
  347.     if (eq(vp, STRpath)) {
  348.         exportpath(adrof(STRpath)->vec);
  349.         dohash(NULL, NULL);
  350.     }
  351. #ifdef __MINT__
  352.     else if (eq(vp, STRsuffixes)) {
  353.         exportsuffixes(adrof(STRsuffixes)->vec);
  354.         dohash(NULL, NULL);
  355.     }
  356. #endif
  357.     xfree((ptr_t) vp);
  358.     if (c != '=')
  359.         xfree((ptr_t) p);
  360.     } while (p = *v++);
  361. }
  362.  
  363. static Char *
  364. xset(cp, vp)
  365.     Char   *cp, ***vp;
  366. {
  367.     register Char *dp;
  368.  
  369.     if (*cp) {
  370.     dp = Strsave(cp);
  371.     --(*vp);
  372.     xfree((ptr_t) ** vp);
  373.     **vp = dp;
  374.     }
  375.     return (putn(exp(vp)));
  376. }
  377.  
  378. static Char *
  379. operate(op, vp, p)
  380.     int     op;
  381.     Char    *vp, *p;
  382. {
  383.     Char    opr[2];
  384.     Char   *vec[5];
  385.     register Char **v = vec;
  386.     Char  **vecp = v;
  387.     register int i;
  388.  
  389.     if (op != '=') {
  390.     if (*vp)
  391.         *v++ = vp;
  392.     opr[0] = op;
  393.     opr[1] = 0;
  394.     *v++ = opr;
  395.     if (op == '<' || op == '>')
  396.         *v++ = opr;
  397.     }
  398.     *v++ = p;
  399.     *v++ = 0;
  400.     i = exp(&vecp);
  401.     if (*vecp)
  402.     stderror(ERR_NAME | ERR_EXPRESSION);
  403.     return (putn(i));
  404. }
  405.  
  406. static Char *putp;
  407.  
  408. Char   *
  409. putn(n)
  410.     register int n;
  411. {
  412.     int     num;
  413.     static Char number[15];
  414.  
  415.     putp = number;
  416.     if (n < 0) {
  417.     n = -n;
  418.     *putp++ = '-';
  419.     }
  420.     num = 2;            /* comfuse lint */
  421.     if (sizeof(int) == num && n == -32768) {
  422.     *putp++ = '3';
  423.     n = 2768;
  424. #ifdef pdp11
  425.     }
  426. #else
  427.     }
  428.     else {
  429.     num = 4;        /* comfuse lint */
  430.     if (sizeof(int) == num && n == -2147483648) {
  431.         *putp++ = '2';
  432.         n = 147483648;
  433.     }
  434.     }
  435. #endif
  436.     putn1(n);
  437.     *putp = 0;
  438.     return (Strsave(number));
  439. }
  440.  
  441. static void
  442. putn1(n)
  443.     register int n;
  444. {
  445.     if (n > 9)
  446.     putn1(n / 10);
  447.     *putp++ = n % 10 + '0';
  448. }
  449.  
  450. int
  451. getn(cp)
  452.     register Char *cp;
  453. {
  454.     register int n;
  455.     int     sign;
  456.  
  457.     if (!cp)            /* PWP: extra error checking */
  458.     stderror(ERR_NAME | ERR_BADNUM);
  459.  
  460.     sign = 0;
  461.     if (cp[0] == '+' && cp[1])
  462.     cp++;
  463.     if (*cp == '-') {
  464.     sign++;
  465.     cp++;
  466.     if (!Isdigit(*cp))
  467.         stderror(ERR_NAME | ERR_BADNUM);
  468.     }
  469.     n = 0;
  470.     while (Isdigit(*cp))
  471.     n = n * 10 + *cp++ - '0';
  472.     if (*cp)
  473.     stderror(ERR_NAME | ERR_BADNUM);
  474.     return (sign ? -n : n);
  475. }
  476.  
  477. Char   *
  478. value1(var, head)
  479.     Char   *var;
  480.     struct varent *head;
  481. {
  482.     register struct varent *vp;
  483.  
  484.     if (!var || !head)        /* PWP: extra error checking */
  485.     return (STRNULL);
  486.  
  487.     vp = adrof1(var, head);
  488.     return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
  489. }
  490.  
  491. static struct varent *
  492. madrof(pat, vp)
  493.     Char   *pat;
  494.     register struct varent *vp;
  495. {
  496.     register struct varent *vp1;
  497.  
  498.     for (; vp; vp = vp->v_right) {
  499.     if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))
  500.         return vp1;
  501.     if (Gmatch(vp->v_name, pat))
  502.         return vp;
  503.     }
  504.     return vp;
  505. }
  506.  
  507. struct varent *
  508. adrof1(name, v)
  509.     register Char *name;
  510.     register struct varent *v;
  511. {
  512.     register cmp;
  513.  
  514.     v = v->v_left;
  515.     while (v && ((cmp = *name - *v->v_name) || (cmp = Strcmp(name, v->v_name))))
  516.     if (cmp < 0)
  517.         v = v->v_left;
  518.     else
  519.         v = v->v_right;
  520.     return v;
  521. }
  522.  
  523. /*
  524.  * The caller is responsible for putting value in a safe place
  525.  */
  526. void
  527. set(var, val)
  528.     Char   *var, *val;
  529. {
  530.     register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
  531.  
  532.     vec[0] = val;
  533.     vec[1] = 0;
  534.     set1(var, vec, &shvhed);
  535. }
  536.  
  537. void
  538. set1(var, vec, head)
  539.     Char   *var, **vec;
  540.     struct varent *head;
  541. {
  542.     register Char **oldv = vec;
  543.  
  544.     gflag = 0;
  545.     tglob(oldv);
  546.     if (gflag) {
  547.     vec = globall(oldv);
  548.     if (vec == 0) {
  549.         blkfree(oldv);
  550.         stderror(ERR_NAME | ERR_NOMATCH);
  551.         return;
  552.     }
  553.     blkfree(oldv);
  554.     gargv = 0;
  555.     }
  556.     setq(var, vec, head);
  557. }
  558.  
  559.  
  560. void
  561. setq(name, vec, p)
  562.     Char   *name, **vec;
  563.     register struct varent *p;
  564. {
  565.     register struct varent *c;
  566.     register f;
  567.  
  568.     f = 0;            /* tree hangs off the header's left link */
  569.     while (c = p->v_link[f]) {
  570.     if ((f = *name - *c->v_name) == 0 &&
  571.         (f = Strcmp(name, c->v_name)) == 0) {
  572.         blkfree(c->vec);
  573.         goto found;
  574.     }
  575.     p = c;
  576.     f = f > 0;
  577.     }
  578.     p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
  579.     c->v_name = Strsave(name);
  580.     c->v_bal = 0;
  581.     c->v_left = c->v_right = 0;
  582.     c->v_parent = p;
  583.     balance(p, f, 0);
  584. found:
  585.     trim(c->vec = vec);
  586. }
  587.  
  588. /*ARGSUSED*/
  589. void
  590. unset(v, c)
  591.     Char   **v;
  592.     struct command *c;
  593. {
  594.     register bool did_only;
  595.  
  596.     did_only = adrof(STRrecognize_only_executables) != 0;
  597.     unset1(v, &shvhed);
  598.     if (adrof(STRhistchars) == 0) {
  599.     HIST = '!';
  600.     HISTSUB = '^';
  601.     }
  602.     if (adrof(STRhistlit) == 0)
  603.     HistLit = 0;
  604.     if (adrof(STRwordchars) == 0)
  605.     word_chars = STR_WORD_CHARS;
  606.     if (adrof(STRedit) == 0)
  607.     editing = 0;
  608.     if (adrof(STRbackslash_quote) == 0)
  609.     bslash_quote = 0;
  610. #ifdef ALTESC
  611.     if (adrof(STRescchar) == 0) {
  612.     _cmap[escchar] &= ~_ESC;
  613.     escchar = '\\';
  614.     _cmap[escchar] |= _ESC;
  615.     }
  616. #endif
  617. #ifdef __MINT__
  618.     if (adrof(STRdosslashes) == 0)
  619.     STRslash[0] = '/';
  620. #endif
  621.     if (did_only && adrof(STRrecognize_only_executables) == 0)
  622.     tw_clear_comm_list();
  623. }
  624.  
  625. void
  626. unset1(v, head)
  627.     register Char *v[];
  628.     struct varent *head;
  629. {
  630.     register struct varent *vp;
  631.     register int cnt;
  632.  
  633.     while (*++v) {
  634.     cnt = 0;
  635.     while (vp = madrof(*v, head->v_left))
  636.         unsetv1(vp), cnt++;
  637.     if (cnt == 0)
  638.         setname(short2str(*v));
  639.     }
  640. }
  641.  
  642. void
  643. unsetv(var)
  644.     Char   *var;
  645. {
  646.     register struct varent *vp;
  647.  
  648.     if ((vp = adrof1(var, &shvhed)) == 0)
  649.     udvar(var);
  650.     unsetv1(vp);
  651. }
  652.  
  653. static void
  654. unsetv1(p)
  655.     register struct varent *p;
  656. {
  657.     register struct varent *c, *pp;
  658.     register f;
  659.  
  660.     /*
  661.      * Free associated memory first to avoid complications.
  662.      */
  663.     blkfree(p->vec);
  664.     xfree((ptr_t) p->v_name);
  665.     /*
  666.      * If p is missing one child, then we can move the other into where p is.
  667.      * Otherwise, we find the predecessor of p, which is guaranteed to have no
  668.      * right child, copy it into p, and move it's left child into it.
  669.      */
  670.     if (p->v_right == 0)
  671.     c = p->v_left;
  672.     else if (p->v_left == 0)
  673.     c = p->v_right;
  674.     else {
  675.     for (c = p->v_left; c->v_right; c = c->v_right);
  676.     p->v_name = c->v_name;
  677.     p->vec = c->vec;
  678.     p = c;
  679.     c = p->v_left;
  680.     }
  681.     /*
  682.      * Move c into where p is.
  683.      */
  684.     pp = p->v_parent;
  685.     f = pp->v_right == p;
  686.     if (pp->v_link[f] = c)
  687.     c->v_parent = pp;
  688.     /*
  689.      * Free the deleted node, and rebalance.
  690.      */
  691.     xfree((ptr_t) p);
  692.     balance(pp, f, 1);
  693. }
  694.  
  695. void
  696. setNS(cp)
  697.     Char   *cp;
  698. {
  699.     set(cp, Strsave(STRNULL));
  700. }
  701.  
  702. /*ARGSUSED*/
  703. void
  704. shift(v, c)
  705.     register Char **v;
  706.     struct command *c;
  707. {
  708.     register struct varent *argv;
  709.     register Char *name;
  710.  
  711.     v++;
  712.     name = *v;
  713.     if (name == 0)
  714.     name = STRargv;
  715.     else
  716.     (void) strip(name);
  717.     argv = adrof(name);
  718.     if (argv == 0)
  719.     udvar(name);
  720.     if (argv->vec[0] == 0)
  721.     stderror(ERR_NAME | ERR_NOMORE);
  722.     lshift(argv->vec, 1);
  723. }
  724.  
  725. static void
  726. exportpath(val)
  727.     Char  **val;
  728. {
  729.     Char    exppath[BUFSIZ];
  730.  
  731.     exppath[0] = 0;
  732.     if (val)
  733.     while (*val) {
  734.         if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZ) {
  735.         xprintf("Warning: ridiculously long PATH truncated\n");
  736.         break;
  737.         }
  738.         (void) Strcat(exppath, *val++);
  739.         if (*val == 0 || eq(*val, STRRparen))
  740.         break;
  741.         (void) Strcat(exppath, STRcolon);
  742.     }
  743.     Setenv(STRPATH, exppath);
  744. }
  745.  
  746. #ifdef __MINT__
  747. static void
  748. exportsuffixes(val)
  749.     Char  **val;
  750. {
  751.     Char    expsuff[BUFSIZ];
  752.     static Char STRcomma[] = { ',' , '\0' };
  753.  
  754.     expsuff[0] = 0;
  755.     if (val)
  756.     while (*val) {
  757.         if (Strlen(*val) + Strlen(expsuff) + 2 > BUFSIZ) {
  758.         xprintf("Warning: ridiculously long SUFFIXES truncated\n");
  759.         break;
  760.         }
  761.         (void) Strcat(expsuff, *val++);
  762.         if (*val == 0 || eq(*val, STRRparen))
  763.         break;
  764.         (void) Strcat(expsuff, STRcomma);
  765.     }
  766.     Setenv(STRSUFFIXES, expsuff);
  767. }
  768. #endif /* __MINT__ */
  769.  
  770. #ifndef lint
  771.  /*
  772.   * Lint thinks these have null effect
  773.   */
  774.  /* macros to do single rotations on node p */
  775. #define rright(p) (\
  776.     t = (p)->v_left,\
  777.     (t)->v_parent = (p)->v_parent,\
  778.     ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
  779.     (t->v_right = (p))->v_parent = t,\
  780.     (p) = t)
  781. #define rleft(p) (\
  782.     t = (p)->v_right,\
  783.     (t)->v_parent = (p)->v_parent,\
  784.     ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
  785.     (t->v_left = (p))->v_parent = t,\
  786.     (p) = t)
  787. #else
  788. struct varent *
  789. rleft(p)
  790.     struct varent *p;
  791. {
  792.     return (p);
  793. }
  794. struct varent *
  795. rright(p)
  796.     struct varent *p;
  797. {
  798.     return (p);
  799. }
  800.  
  801. #endif                /* ! lint */
  802.  
  803.  
  804. /*
  805.  * Rebalance a tree, starting at p and up.
  806.  * F == 0 means we've come from p's left child.
  807.  * D == 1 means we've just done a delete, otherwise an insert.
  808.  */
  809. static void
  810. balance(p, f, d)
  811.     register struct varent *p;
  812.     register int f, d;
  813. {
  814.     register struct varent *pp;
  815.  
  816. #ifndef lint
  817.     register struct varent *t;    /* used by the rotate macros */
  818.  
  819. #endif
  820.     register ff;
  821.  
  822.     /*
  823.      * Ok, from here on, p is the node we're operating on; pp is it's parent; f
  824.      * is the branch of p from which we have come; ff is the branch of pp which
  825.      * is p.
  826.      */
  827.     for (; pp = p->v_parent; p = pp, f = ff) {
  828.     ff = pp->v_right == p;
  829.     if (f ^ d) {        /* right heavy */
  830.         switch (p->v_bal) {
  831.         case -1:        /* was left heavy */
  832.         p->v_bal = 0;
  833.         break;
  834.         case 0:        /* was balanced */
  835.         p->v_bal = 1;
  836.         break;
  837.         case 1:        /* was already right heavy */
  838.         switch (p->v_right->v_bal) {
  839.         case 1:    /* sigle rotate */
  840.             pp->v_link[ff] = rleft(p);
  841.             p->v_left->v_bal = 0;
  842.             p->v_bal = 0;
  843.             break;
  844.         case 0:    /* single rotate */
  845.             pp->v_link[ff] = rleft(p);
  846.             p->v_left->v_bal = 1;
  847.             p->v_bal = -1;
  848.             break;
  849.         case -1:    /* double rotate */
  850.             (void) rright(p->v_right);
  851.             pp->v_link[ff] = rleft(p);
  852.             p->v_left->v_bal =
  853.             p->v_bal < 1 ? 0 : -1;
  854.             p->v_right->v_bal =
  855.             p->v_bal > -1 ? 0 : 1;
  856.             p->v_bal = 0;
  857.             break;
  858.         }
  859.         break;
  860.         }
  861.     }
  862.     else {            /* left heavy */
  863.         switch (p->v_bal) {
  864.         case 1:        /* was right heavy */
  865.         p->v_bal = 0;
  866.         break;
  867.         case 0:        /* was balanced */
  868.         p->v_bal = -1;
  869.         break;
  870.         case -1:        /* was already left heavy */
  871.         switch (p->v_left->v_bal) {
  872.         case -1:    /* single rotate */
  873.             pp->v_link[ff] = rright(p);
  874.             p->v_right->v_bal = 0;
  875.             p->v_bal = 0;
  876.             break;
  877.         case 0:    /* signle rotate */
  878.             pp->v_link[ff] = rright(p);
  879.             p->v_right->v_bal = -1;
  880.             p->v_bal = 1;
  881.             break;
  882.         case 1:    /* double rotate */
  883.             (void) rleft(p->v_left);
  884.             pp->v_link[ff] = rright(p);
  885.             p->v_left->v_bal =
  886.             p->v_bal < 1 ? 0 : -1;
  887.             p->v_right->v_bal =
  888.             p->v_bal > -1 ? 0 : 1;
  889.             p->v_bal = 0;
  890.             break;
  891.         }
  892.         break;
  893.         }
  894.     }
  895.     /*
  896.      * If from insert, then we terminate when p is balanced. If from
  897.      * delete, then we terminate when p is unbalanced.
  898.      */
  899.     if ((p->v_bal == 0) ^ d)
  900.         break;
  901.     }
  902. }
  903.  
  904. void
  905. plist(p)
  906.     register struct varent *p;
  907. {
  908.     register struct varent *c;
  909.     register len;
  910.  
  911.     if (setintr)
  912. #ifdef BSDSIGS
  913.     (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
  914. #else                /* BSDSIGS */
  915.     (void) sigrelse(SIGINT);
  916. #endif                /* BSDSIGS */
  917.  
  918.     for (;;) {
  919.     while (p->v_left)
  920.         p = p->v_left;
  921. x:
  922.     if (p->v_parent == 0)    /* is it the header? */
  923.         return;
  924.     len = blklen(p->vec);
  925.     xprintf(short2str(p->v_name));
  926.     xputchar('\t');
  927.     if (len != 1)
  928.         xputchar('(');
  929.     blkpr(p->vec);
  930.     if (len != 1)
  931.         xputchar(')');
  932.     xputchar('\n');
  933.     if (p->v_right) {
  934.         p = p->v_right;
  935.         continue;
  936.     }
  937.     do {
  938.         c = p;
  939.         p = p->v_parent;
  940.     } while (p->v_right == c);
  941.     goto x;
  942.     }
  943. }
  944.